import datetime
import hashlib
import json
import os

import string
import uuid
from random import randrange, random

from django.contrib.auth import authenticate
from django.core.mail import send_mail

from django.http import request, HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render, redirect, render_to_response
from django.conf import settings
from django import forms
from django.views.decorators.csrf import csrf_exempt

# from JanshuBlog.settings import EMAIL_FROM
from blog import models

from blog.models import Bloguser, ConfirmString, Article
from  django.contrib.auth.hashers import make_password,check_password
from  blog.form import UserForm
from  blog.form import RegisterForm
make_password("明码")
check_password("明码","加密串")

def index(request):
   #return HttpResponse("ok")
    lists = Article.objects.all()[0:page_size]
    page_index = 1
   # return  render(request,"home/index.html",locals())
    return render_to_response("home/index.html",locals())


def hash_code(s, salt='blog'):
   h = hashlib.sha256()
   s += salt
   h.update(s.encode())
   return h.hexdigest()



def register(request):
   if request.session.get('is_login', None):
      return render(request, 'home/index.html', locals())

   if request.method == 'POST':
      register_form = RegisterForm(request.POST)
      message = "请检查填写的内容！"
      if register_form.is_valid():
         username = register_form.cleaned_data.get('username')
         tel = register_form.cleaned_data.get('tel')
         email = register_form.cleaned_data.get('email')
         password1 = register_form.cleaned_data.get('password1')
         password2 = register_form.cleaned_data.get('password2')

         if password1 != password2:
            message = '两次输入的密码不同！'
            return render(request, 'home/register.html', locals())
         else:
            same_name_user = models.Bloguser.objects.filter(nick_name=username)
            if same_name_user:
               message = '用户名已经存在'
               return render(request, 'home/register.html', locals())
            same_email_user = models.Bloguser.objects.filter(email=email)
            if same_email_user:
               message = '该邮箱已经被注册了！'
               return render(request, 'home/register.html', locals())
            same_tel_user = models.Bloguser.objects.filter(mobile_number=tel)
            if same_tel_user:
                message = '该手机号已经被注册了！'
                return render(request, 'home/register.html', locals())

            new_user = Bloguser()
            new_user.nick_name = username
            new_user.password = password1
            new_user.password = make_password(password1)
            new_user.email = email
            new_user.mobile_number = tel
            new_user.save()

            new_user.password = make_password(new_user.password)
            code = make_confirm_string(new_user)
            send_email(email, code)

            message = '请前往邮箱进行确认！'
            return render(request, 'home/confirm.html', locals())
      else:
         return render(request, 'home/register.html', locals())
   register_form = RegisterForm()
   return render(request, 'home/register.html', locals())


def login(request):
   if request.session.get('is_login', None):
      # return redirect('/index/')
      return render(request, 'home/index.html', locals())

   if request.method == "POST":
      login_form = UserForm(request.POST)
      message = "请检查填写的内容！"
      if login_form.is_valid():
         ema = login_form.cleaned_data['email']
         password = login_form.cleaned_data['password']

         try:
            user = models.Bloguser.objects.get(email=ema)
            ps=user.password
         except:
            message = "用户不存在！"
            return render(request, 'home/login.html', locals())

         if  user.has_confirmed == False:
               message = '该用户还未经过邮件确认！'
               return render(request, 'home/login.html', locals())
         if check_password(password,ps):
               request.session['is_login'] = True
               request.session['user_id'] = user.id
               request.session['user_name'] = user.nick_name
               # return redirect('home/index/')
               lists = Article.objects.all()[0:page_size]
               page_index = 1
               # return  render(request,"home/index.html",locals())
               return render_to_response("home/index.html", locals())
         else:
               message = "密码不正确！"
      else:
         return render(request, 'home/login.html', locals())
   login_form = UserForm()
   return render(request, 'home/login.html', locals())


def logout(request):
   if not request.session.get('is_login', None):
      # 如果本来就未登录，也就没有登出一说
      return render(request, 'home/index.html', locals())
   request.session.flush()
   lists = Article.objects.all()[0:page_size]
   page_index = 1
   # return  render(request,"home/index.html",locals())
   return render_to_response("home/index.html", locals())



def make_confirm_string(user):
   now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
   code = hash_code(user.nick_name, now)
   models.ConfirmString.objects.create(code=code, user=user, )
   return code
#make_confirm_string()方法接收一个用户对象作为参数。首先利用datetime模块生成一个当前时间的字符串now，
# 再调用我们前面编写的hash_code()方法以用户名为基础，now为‘盐’，生成一个独一无二的哈希值，
# 再调用ConfirmString模型的create()方法，生成并保存一个确认码对象。最后返回这个哈希值。





def user_confirm(request):
   code = request.GET.get('code', None)
   message = ''
   try:
      confirm = models.ConfirmString.objects.get(code=code)
   except:
      message = '无效的确认请求!'
      return render(request, 'home/confirm.html', locals())

   c_time = confirm.c_time
   now = datetime.datetime.now()
   if now > c_time + datetime.timedelta(settings.CONFIRM_DAYS):
      confirm.user.delete()
      message = '您的邮件已经过期！请重新注册!'
      return render(request, 'home/confirm.html', locals())
   else:
      confirm.user.has_confirmed = True
      confirm.user.save()
      confirm.delete()
      message = '感谢确认，请使用账户登录！'
      return render(request, 'home/confirm.html', locals())
#通过request.GET.get('code', None)从请求的url地址中获取确认码;
#先去数据库内查询是否有对应的确认码;
#如果没有，返回confirm.html页面，并提示;
# 如果有，获取注册的时间c_time，加上设置的过期天数，这里是7天，然后与现在时间点进行对比；
# 如果时间已经超期，删除注册的用户，同时注册码也会一并删除，然后返回confirm.html页面，并提示;
# 如果未超期，修改用户的has_confirmed字段为True，并保存，表示通过确认了。然后删除注册码，但不删除用户本身。最后返回confirm.html页面，并提示。

from django.conf import settings

def send_email(email, code):

    from django.core.mail import EmailMultiAlternatives

    subject = '来自www.ccblog.com的注册确认邮件'

    text_content = '''感谢注册www.ccblog.com，这里是刘江的博客和教程站点，专注于Python、Django和机器学习技术的分享！\
                    如果你看到这条消息，说明你的邮箱服务器不提供HTML链接功能，请联系管理员！'''

    html_content = '''
                    <p>感谢注册<a href="http://{}/confirm/?code={}" target=blank>www.liujiangblog.com</a>，\
                    这里xd博客和教程站点，专注于Python、Django和机器学习技术的分享！</p>
                    <p>请点击站点链接完成注册确认！</p>
                    <p>此链接有效期为{}天！</p>
                    '''.format('127.0.0.1:8000', code, settings.CONFIRM_DAYS)

    msg = EmailMultiAlternatives(subject, text_content, settings.EMAIL_HOST_USER, [email])
    msg.attach_alternative(html_content, "text/html")
    msg.send()



#上传图片
@csrf_exempt
def upload_image(request):
    allow_suffix=['jpg','png','jpeg','gif']
    files=request.FILES.get("imgFile",None)
    if files:
        file_suffix=files.name.split(".")[-1]
        if file_suffix not in allow_suffix:
            return JsonResponse({"error":1,"message":"图片格式不正确"})
        file_name=str(uuid.uuid1())+"."+file_suffix
        file_path=os.path.join(settings.MEDIA_ROOT,'image',file_name)
        url_path=os.path.join(settings.MEDIA_URL,'image',file_name)
        with open(file_path, 'wb') as f:
            f.write(files.file.read())
        return JsonResponse({"error":0,"url":url_path})

#加载详情页
def detail(request,nid):
    news = Article.objects.get(id = nid)

    return render(request,'home/articledetail.html',{'detail':news})


#加载更多
#Page_size为全局配置，从settings中读取。核心原理为生成mysql数据库中的limit关键字，控制数据的返回。Start 为开始索引，索引从0开始，end为结束索引。
#Article.objects.all()[start:end]为获取指定的分页数据，并返回所有的列。由于文章内容长度为text，增加网络传输的难度，使用values返回指定的列，并将结果转换为list

def get_index_more(request):
    page_index=request.GET.get("page_index")
    article_list=indexpage(page_index)
    if len(article_list)>0:
        result_dict={"status":"ok","pageindex":int(page_index)+1,"data":article_list}
    else:
        result_dict={"status":"no"}
    return JsonResponse(json.dumps(result_dict),safe=False)
#
page_size=settings.PAGE_SIZE
def indexpage(page_index=0):
    start=int(page_index) *page_size
    end=int(start)+int(page_size)
    return list(Article.objects.all()[start:end].
                values("id","title","author","abstract","reply_num","read_num","like_num"))






#点赞、拍砖
def digg(request):

    # ajax 是json格式，特殊情况下需要反序列
    import json
    from django.db.models import F  # 利用F来做自加1操作

    article_id = request.POST.get('article_id')

    is_up = json.loads(request.POST.get('is_up'))  # 必须反序列化才能为布尔值
    # 点赞人即当前登陆人
    user_id = request.user.pk

    # 过滤已经点赞或者踩了的
    obj = models.Article.objects.filter(user_id=user_id, article_id=article_id).first()

    # 返回json
    response = {'state': True, 'msg': None}

    if not obj:
        ard = models.Article.objects.create(user_id=user_id, article_id=article_id, is_up=True)
        # 生成了赞记录， 然后再来更新页面
        if is_up:  # 如果是赞就更新赞
            models.Article.objects.filter(pk=article_id).update(up_count=F('up_count')+1)
        else:
            # 踩的时候
            models.Article.objects.filter(pk=article_id).update(down_count=F('down_count')+1)
    else:
        response['state'] = False
        response['handled'] = obj.is_up  # 将已经做过的操作提示

    return JsonResponse(response)  # 必须用json返回





